/*
 * Schedule.java
 * 
 * Copyright (c) 2008, Marshall Scorcio, Ralph Holzmann, 
 *                     Stewart Sweet, Tyler Hoersch, Jeffery Van Handel
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the University of Wisconsin Oshkosh nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

import java.util.Vector;

public class Schedule implements java.io.Serializable
{       
    private Vector<ScheduledDay> scheduledDays;
        
    public Schedule(int startDayOfWeek, int startDayOfMonth, int startMonth, int startYear)
    {        
        initializeDays(startDayOfWeek, startDayOfMonth, startMonth, startYear);
    }
    
    public Schedule(String startDay)
    {   
        int startDayOfWeek;
        int startDayOfMonth;
        int startMonth;
        int startYear;
        
        startDayOfWeek = Day.getDayOfWeekFromName(startDay.substring(0, startDay.indexOf(",")));
        startDay = startDay.substring(startDay.indexOf(",") + 2);

        startMonth = Day.getMonthFromName(startDay.substring(0, startDay.indexOf(" ")));
        startDay = startDay.substring(startDay.indexOf(" ") + 1);

        startDayOfMonth = Integer.parseInt(startDay.substring(0, startDay.indexOf(", ")));
        startDay = startDay.substring(startDay.indexOf(",") + 2);
                
        startYear = Integer.parseInt(startDay);
        
        initializeDays(startDayOfWeek, startDayOfMonth, startMonth, startYear);
    }

    private void initializeDays(int startDayOfWeek, int startDayOfMonth, int startMonth, int startYear)
    {
        int dayOfWeek = startDayOfWeek;
        int dayOfMonth = startDayOfMonth;
        int month = startMonth;
        int year = startYear;
        
        scheduledDays = new Vector<ScheduledDay>(7);
        scheduledDays.add(new ScheduledDay(startDayOfWeek, startDayOfMonth, startMonth, startYear));
        
        for (int i = 1; i < 7; i++)
        {
            if ((month == Day.JANUARY || month == Day.MARCH || month == Day.MAY || month == Day.JULY ||
                 month == Day.AUGUST || month == Day.OCTOBER || month == Day.DECEMBER)
                && (dayOfMonth == 31))
            {
                if (month == Day.DECEMBER)
                {
                    year++;
                    month = Day.JANUARY;
                }
                else
                {
                    month++;
                }
                
                dayOfMonth = 1;
            }
            else if ((month == Day.APRIL || month == Day.JUNE || month == Day.SEPTEMBER || month == Day.NOVEMBER)
                     && (dayOfMonth == 30))
            {
                month++;
                dayOfMonth = 1;
            }
            else if ((month == Day.FEBRUARY) && (dayOfMonth >= 28))
            {
                if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))
                {
                    if (dayOfMonth == 29)
                    {
                        month++;
                        dayOfMonth = 1;
                    }
                    else
                    {
                        dayOfMonth++;
                    }
                } 
                else
                {
                    month++;
                    dayOfMonth = 1;
                }
            }
            else
            {
                dayOfMonth++;
            }

            dayOfWeek = (dayOfWeek + 1) % 7;

            scheduledDays.add(new ScheduledDay(dayOfWeek, dayOfMonth, month, year));
        }
    }
    
    public void addScheduledShiftAt(Shift shift, int dayOfWeek)
    {
        ScheduledDay scheduledDay = getScheduledDayByDayOfWeek(dayOfWeek);
        if (scheduledDay != null)
        {
            scheduledDay.addShift(shift);
        }
    }

    public void removeScheduledShiftAt(Shift shift, int dayOfWeek)
    {
        ScheduledDay scheduledDay = getScheduledDayByDayOfWeek(dayOfWeek);
        if (scheduledDay != null)
        {
            scheduledDay.removeShift(shift);
        }
    }
    
    public ScheduledDay getScheduledDayByDayOfWeek(int dayOfWeek)
    {
        ScheduledDay scheduledDay = null;
        
        for (int i = 0; i < 7; i++)
        {
            if (scheduledDays.elementAt(i).getDayOfWeek() == dayOfWeek)
            {
                scheduledDay = scheduledDays.elementAt(i);
            }
        }
        
        return scheduledDay;
    }
    
    public ScheduledDay getScheduledDayByIndex(int index)
    {
        ScheduledDay scheduledDay = null;
        
        if (index < scheduledDays.size())
        {
            scheduledDay = scheduledDays.elementAt(index);
        }
        
        return scheduledDay;
    }
    
    public Vector<ScheduledDay> getScheduledDays()
    {
        return scheduledDays;
    }
    
    public Vector<String> getScheduleFor(int dayOfWeek)
    {
        Vector<String> schedule = null;
        ScheduledDay scheduledDay = getScheduledDayByDayOfWeek(dayOfWeek);
        
        if (scheduledDay != null)
        {
            schedule = scheduledDay.getSchedule();
        }
        
        return schedule;
    }
    
    public String[][] getFullSchedule(Vector<Employee> allEmployees)
    {
        String[][] fullSchedule = new String[allEmployees.size() + 1][];
        
        String[] columnTitles = new String[8];
        columnTitles[0] = "Employee Name";
        for (int i = 0; i < 7; i++)
        {
            columnTitles[i + 1] = Day.getNameFromDayOfWeek(getScheduledDayByIndex(i).getDayOfWeek());
        }
        
        fullSchedule[0] = columnTitles;
        
        for (int i = 0; i < allEmployees.size(); i++)
        {
            String[] employeeRow = new String[8];
            employeeRow[0] = allEmployees.elementAt(i).getName();

            for (int j = 0; j < 7; j++)
            {
                String time = " ";
                ScheduledDay day = getScheduledDayByIndex(j);

                for (int k = 0; k < day.getNumberOfShifts(); k++)
                {
                   Shift shift = day.getShiftAt(k);
                   Vector<Employee> shiftEmployees = shift.getEmployees();
                   
                   for (int l = 0; l < shiftEmployees.size(); l++)
                   {
                       if (shiftEmployees.elementAt(l).getName().equals(allEmployees.elementAt(i).getName()))
                       {
                           time = shift.timeToString();
                       }
                   }
                }     
                employeeRow[j + 1] = time;
            }
            fullSchedule[i + 1] = employeeRow;
        }
        
        return fullSchedule;
    }
    
    @Override
    public String toString()
    {
        StringBuilder formatted = new StringBuilder();
        formatted.append(scheduledDays.firstElement().toString());
        formatted.append(" - ");
        formatted.append(scheduledDays.lastElement().toString());
        return formatted.toString();
    }
}
